package math;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.TreeMap;

public class ApplyRulesCollector implements Iterable<Expression>{

  private Rater rater;
  
  private TreeMap<Integer, Set<Expression>> expressions;
  
  private int size;
  
  public ApplyRulesCollector(Rater rater) {
    this.rater = rater;
    expressions = new TreeMap<Integer, Set<Expression>>();
  }
  
  @Override
  public Iterator<Expression> iterator() {
    return toList().iterator();
  }

  public void addAll(List<Expression> newExpressions) {
    for (Expression expression: newExpressions)
      add(expression);
  }

  public List<Expression> toList() {
    ArrayList<Expression> list = new ArrayList<Expression>();
    for (Set<Expression> entry: expressions.values()){
      list.addAll(entry);
    }
    return list;
  }

  public boolean contains(Expression ae) {
    int rating = rater.rate(ae);
    Set<Expression> set = expressions.get(Integer.valueOf(rating));
    return set != null && set.contains(ae);
  }

  public boolean add(Expression ae) {
    int rating = rater.rate(ae);
    Set<Expression> set = expressions.get(Integer.valueOf(rating));
    if (set == null){
      set = new HashSet<Expression>();
      expressions.put(Integer.valueOf(rating), set);
    }
    boolean added = set.add(ae);
    if (added){
      size++;
//      System.out.println(size + " " + getMinRating()+ " " + getMaxRating());
//      if (getMinRating() == 32)
//        System.out.println(ae);
    }
    
    while (expressions.size() > 1){
      System.out.println("removing: " + expressions.keySet());
      
      Integer key = expressions.lastKey();
      Set<Expression> removed = expressions.remove(key);
      System.out.println(key + " (" + removed.size() + ")");
    }
    
    
    return added;
  }
  
  public int getSize() {
    return size;
  }
  
  public int getMinRating() throws NoSuchElementException{
    return expressions.firstKey().intValue();
  }
  
  public boolean isEmpty(){
    return size == 0;
  }
  
  public int getMaxRating() throws NoSuchElementException{
    return expressions.lastKey().intValue();
  }

  public Set<Expression> getExpressionsByRating(int rating){
    return expressions.get(Integer.valueOf(rating));
  }
  
  public Collection<Expression> elements() {
    return toList();
  }

  public Rater getRater() {
    return rater;
  }
  
  @Override
  public String toString() {
    boolean appending = false;
    StringBuilder sb = new StringBuilder();
    sb.append('[');
    for (Integer key: expressions.keySet()){
      if (appending)
        sb.append(", ");
      else 
        appending = true;
      sb.append(key);
      sb.append("={");
      Set<Expression> elements = expressions.get(key);
      sb.append(elements);
      sb.append('}');
    }
    sb.append(']');
    return sb.toString();
  }
}